Skip to content

fix(cli-detect): detect native Kimi Code (code.kimi.com) build (#98)#99

Merged
chorus-codes merged 1 commit into
mainfrom
fix/kimi-code-detection
May 30, 2026
Merged

fix(cli-detect): detect native Kimi Code (code.kimi.com) build (#98)#99
chorus-codes merged 1 commit into
mainfrom
fix/kimi-code-detection

Conversation

@chorus-codes
Copy link
Copy Markdown
Owner

Closes #98.

The two-kimi problem

@theeasypet reported that Kimi Code (the native CLI from code.kimi.com, installed to ~/.kimi-code/bin/kimi) isn't detected. Investigation showed the two "kimi" CLIs are old and new builds of the same product, not rivals:

Python kimi-cli (legacy) native Kimi Code (new)
Source MoonshotAI/kimi-cli (pip/uv/npm) code.kimi.com installer
Install dir ~/.kimi/bin ~/.kimi-code/bin
--version kimi, version 1.46.0 bare 0.6.0
Auth ~/.kimi/config.toml model kimi login (account)
Headless interface kimi --print --output-format stream-json identical (confirmed via code.kimi.com docs)

The native installer renames any prior Python build to kimi-legacy — Moonshot is migrating users to the native binary. Since both share the same headless contract chorus already drives, this stays one lineage; detection just never recognised the new build.

Why the one-line regex relax (from the issue) isn't enough

Relaxing the signature alone makes a Kimi-Code-only user "detected but broken": with no ~/.kimi/config.toml, detectKimiTransport() falls through to the opencode-go path, so reviews either fail (no OpenCode Go sub) or silently ignore the kimi binary they installed. This PR fixes detection and transport.

Changes

  1. Detection (cli-detect.ts) — accept a bare semver in the kimi --version signature. The basename allowlist still gates on the binary being named kimi, so it's as safe as the existing gemini/opencode bare-version matchers.
  2. Fallback path (cli-detect.ts) — probe ~/.kimi-code/bin alongside ~/.kimi/bin.
  3. Transport (kimi.ts) — extract a pure, testable chooseKimiTransport(homeDir, override); when ~/.kimi-code exists, drive kimi directly instead of routing to opencode-go. Precedence: env override → ~/.kimi-code → configured ~/.kimi/config.toml → opencode-go.

Tests

  • cli-detect-utils.test.ts: accepts kimi, version 1.46.0 (legacy) and bare 0.6.0 (native); still rejects junk --version.
  • kimi-transport.test.ts (new): 8 cases over the full transport precedence, including the key "~/.kimi-code beats an empty ~/.kimi/config.toml" case and both env overrides.
  • Full suite: 1005 passed (+9). Typecheck clean. No new lint problems.
  • Live smoke through compiled code: real Python kimi v1.46 on the dev box still detected (no regression); bare-semver build detected; ~/.kimi-code → direct transport.
  • Reviewed via chorus review-only (7 independent reviewers) → approved.

Known follow-up (needs reporter verification)

chorus passes -m <model> to the kimi binary. The legacy Python build accepts it; I couldn't verify the native v0.6.0 binary accepts -m locally (not installed on the dev box). 4 reviewers flagged this as a non-blocking watch item. @theeasypet — could you confirm a kimi review actually runs end-to-end after this lands? If -m is rejected by the native build, the follow-up is a one-liner (omit -m for the native transport and let the account default apply).

Two CLIs share the `kimi` binary name: the legacy Python kimi-cli
(MoonshotAI/kimi-cli, ~/.kimi, prints "kimi, version 1.46.0") and the
native Kimi Code build (code.kimi.com installer → ~/.kimi-code, prints a
bare semver "0.6.0", account-authed via `kimi login`). The native
installer even renames the Python build to `kimi-legacy`. Both expose the
same `kimi --print --output-format stream-json` headless interface, so
this is ONE lineage — detection simply never recognised the new build.

- cli-detect: accept a bare semver in the kimi --version signature (the
  basename allowlist still requires the binary be named `kimi`, so this
  is as safe as the existing gemini/opencode bare-version matchers); also
  probe ~/.kimi-code/bin in fallbackPaths for non-PATH installs.
- kimi shim: extract pure, testable chooseKimiTransport(homeDir, override)
  and drive `kimi` directly when ~/.kimi-code exists, instead of falling
  through to opencode-go (which would fail outright without an OpenCode Go
  sub, or silently ignore the user's kimi install).

Tests: bare-semver + legacy signature detection; 8 transport-precedence
cases. Verdict: approved by chorus review-only (7 reviewers).
@chorus-codes chorus-codes merged commit 7efd41e into main May 30, 2026
2 checks passed
@chorus-codes chorus-codes deleted the fix/kimi-code-detection branch May 30, 2026 23:34
chorus-codes added a commit that referenced this pull request May 30, 2026
…stence (#101)

Follow-up to v0.8.61 (#99). chooseKimiTransport decided "drive kimi
directly vs route to opencode-go" on `fs.existsSync(~/.kimi-code)`, but
dispatch resolves the binary by name and detection resolves a concrete
path — these disagree when BOTH kimi builds are installed. If a
~/.kimi-code dir existed but PATH resolved `kimi` to an unconfigured
legacy Python build, v0.8.61 drove it directly → "LLM not set", instead
of falling back to opencode-go.

- New `isNativeKimiBinary(homeDir, binPath)` realpaths BOTH the binary and
  the ~/.kimi-code dir before a lexical containment check, so a symlinked
  binary (/usr/local/bin/kimi → ~/.kimi-code/bin/kimi) OR a symlinked
  ~/.kimi-code dir both compare in the same namespace. Returns undefined
  when the path is unknown so the caller falls back to dir existence.
- chooseKimiTransport now takes a tri-state `isNativeBuild?: boolean`,
  staying fs-light/unit-testable. `false` (resolved, non-native) skips the
  dir shortcut and falls to the config probe — the dual-install fix.
- isPathUnder: `..` guard now matches a real parent ref only, not a child
  segment that merely starts with dots (e.g. `..helpers/bin`).

Tests: +15 (isPathUnder lexical, isNativeKimiBinary incl. symlinked-binary
and symlinked-dir cases, tri-state precedence). Two chorus self-review
rounds: round 1 request_changes (realpath asymmetry) → fixed → round 2
approved by all 7 reviewers.

Note: a fallback-detected kimi whose dir isn't on the spawn PATH still
ENOENTs (runHeadless spawns bare `kimi`) — pre-existing, tracked separately.

Co-authored-by: chorus-codes <280607145+chorus-codes@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Kimi Code (code.kimi.com) is not detected: the --version signature only matches MoonshotAI/kimi-cli

1 participant